﻿//统一文件为utf-8编码编译
#pragma execution_character_set("utf-8")
///////////////////////////////////////////////////////////////////////////
// 文件名:     qtcpsocketclient.cpp
// 描述:
// 作者:      颜磊
// 创建时间:   2024-06-09 00:48
///////////////////////////////////////////////////////////////////////////
#include "qtcpsocketclient.h"
#include "networkstruct.h"

QTcpSocketClient::QTcpSocketClient(QObject *parent) : QThread(parent)
{
    moveToThread(this);
//    connect(this,&QTcpSocketClient::signal_addConnection,this,&QTcpSocketClient::slot_addConnection);
//    connect(this,&QTcpSocketClient::signal_upConnection,this,&QTcpSocketClient::slot_upConnection);
//    connect(this,&QTcpSocketClient::signal_delConnection,this,&QTcpSocketClient::slot_delConnection);
//    connect(this,&QTcpSocketClient::signal_sendData,this,&QTcpSocketClient::signal_sendData);
    start();
}

QTcpSocketClient::~QTcpSocketClient()
{
    for(QMap<uint64_t,QTcpSocketConnectionC*>::iterator it = connectionMap.begin();it !=connectionMap.end();it++){
           QTcpSocketConnectionC *tcpSocketConnectionC = connectionMap.take(it.key());
           tcpSocketConnectionC->close();
           delete tcpSocketConnectionC;
    }
    quit();
    wait();
}

//uint64_t QTcpSocketClient::addConnection(QString serverAddress, uint16_t port)
//{
//    int newConnectionId = getConnectionId();
//    signal_addConnection(newConnectionId,serverAddress,port);
//    return newConnectionId;
//}

//void QTcpSocketClient::upConnection(uint64_t connectionId, QString serverAddress, uint16_t port)
//{
//    signal_upConnection(connectionId, serverAddress, port);
//}

//void QTcpSocketClient::delConnection(uint64_t connectionId)
//{
//    signal_delConnection(connectionId);
//}

//void QTcpSocketClient::sendData(uint64_t connectionId, QByteArray data)
//{
//    signal_sendData(connectionId,data);
//}

void QTcpSocketClient::slot_addConnection(uint64_t connectionId, QString serverAddress, uint16_t port)
{
    qDebug() << __FUNCTION__ << QString("添加网络连接通道");
    bool exist = false;
    for(QMap<uint64_t,QTcpSocketConnectionC*>::iterator it = connectionMap.begin();it !=connectionMap.end();it++){
        if(it.key() == connectionId){
            exist = false;
            break;
        }
    }
    if(!exist){
        qDebug() << __FUNCTION__ << QString("添加一个新的网络连接通道");
        QTcpSocketConnectionC *tcpSocketConnection = new QTcpSocketConnectionC(connectionId,serverAddress,port);
        qRegisterMetaType<uint64_t>("uint64_t");
        connect(tcpSocketConnection,&QTcpSocketConnectionC::signal_recvData,this,&QTcpSocketClient::signal_recvData);
        connect(tcpSocketConnection,&QTcpSocketConnectionC::signal_connectionState,this,&QTcpSocketClient::signal_connectionState);
        tcpSocketConnection->open();
        connectionMap.insert(connectionId,tcpSocketConnection);
    }
    qDebug() << __FUNCTION__ << QString("添加网络连接通道完成");
}

void QTcpSocketClient::slot_upConnection(uint64_t connectionId, QString serverAddress, uint16_t port)
{
    qDebug() << __FUNCTION__ << QString("更新网络连接通道信息");
    QTcpSocketConnectionC *socketConnection = connectionMap[connectionId];
    if(socketConnection != nullptr){
        socketConnection->upConnection(serverAddress, port);
    }
    qDebug() << __FUNCTION__ << QString("更新网络连接通道完成");
}

void QTcpSocketClient::slot_delConnection(uint64_t connectionId)
{
    qDebug() << __FUNCTION__ << QString("删除网络连接通道");
    QTcpSocketConnectionC *socketConnection = connectionMap.take(connectionId);
    if(socketConnection != nullptr){
        socketConnection->close();
        delete socketConnection;
    }
    qDebug() << __FUNCTION__ << QString("删除网络连接通道完成");
}

void QTcpSocketClient::slot_sendData(uint64_t connectionId, QByteArray data)
{
    qDebug() << __FUNCTION__ << QString("向通道%1发送数据").arg(connectionId);
    for(QMap<uint64_t,QTcpSocketConnectionC*>::iterator it = connectionMap.begin();it !=connectionMap.end();it++){
        if(it.key() == connectionId || connectionId==0){
            it.value()->sendData(data);
        }
    }
    qDebug() << __FUNCTION__ << QString("向通道%1发送数据完成").arg(connectionId);
}

void QTcpSocketClient::run()
{
    exec();
}
////============================================TCP连接(客户端)
///

QTcpSocketConnectionC::QTcpSocketConnectionC(uint64_t m_connectionId,QString m_address,uint16_t m_port,QObject *parent) : QThread(parent)
{
    qDebug() << __FUNCTION__ << m_connectionId;
    moveToThread(this);
    connectionId  = m_connectionId;
    address = m_address;
    port = m_port;
    sendPackId = 0;
    nextFrameSerial = 0;
    isOpen = false;
    isConnected = false;
    qRegisterMetaType<QByteArray>("QByteArray");
    connect(this,&QTcpSocketConnectionC::signal_sendData,this,&QTcpSocketConnectionC::slot_sendData);
    connect(this,&QTcpSocketConnectionC::signal_reStartConnectTimer,this,&QTcpSocketConnectionC::slot_reStartConnectTimer);//Qt::DirectConnection
    connect(this,&QTcpSocketConnectionC::signal_openSocket,this,&QTcpSocketConnectionC::slot_openSocket);//Qt::DirectConnection
    connect(this,&QTcpSocketConnectionC::signal_closeSocket,this,&QTcpSocketConnectionC::slot_closeSocket);
    start();
}

QTcpSocketConnectionC::~QTcpSocketConnectionC()
{
    qDebug() << __FUNCTION__;
    quit();
    wait();
}

void QTcpSocketConnectionC::open()
{
    signal_openSocket();
}

void QTcpSocketConnectionC::close()
{
    signal_closeSocket();
}

void QTcpSocketConnectionC::sendData(QByteArray data)
{
    signal_sendData(data);
}

void QTcpSocketConnectionC::upConnection(QString serverAddress, uint16_t m_port)
{
    qDebug()<< __FUNCTION__ << QString("连接配置修改！");
    if((serverAddress != address) || (port != m_port)){
        address = serverAddress;
        port = m_port;
        signal_reStartConnectTimer();
    }
    qDebug()<< __FUNCTION__ << QString("连接配置完成！");
}

void QTcpSocketConnectionC::slot_tcpSocketReadyRead()
{
    QByteArray byteArray = tcpSocket->readAll();
    parsingFrameData(byteArray);
}

void QTcpSocketConnectionC::slot_tcpSocketConnected()
{
    qDebug()<< __FUNCTION__ << QString("连接成功处理！");
    if(connectTimer->isActive()){
        connectTimer->stop();
        isConnected = true;
    }
    qDebug()<< __FUNCTION__ << QString("连接成功处理完成！");
    signal_connectionState(connectionId,true);
}

void QTcpSocketConnectionC::slot_tcpSocketDisconnected()
{
    qDebug()<< __FUNCTION__ << QString("连接断开，开始重连处理");
    if(!connectTimer->isActive()){
        isConnected = false;
        connectTimer->start();
    }
    qDebug()<< __FUNCTION__ << QString("连接断开，开始重连处理完成");
    signal_connectionState(connectionId,false);
}

void QTcpSocketConnectionC::slot_reStartConnectTimer()
{
    if(!connectTimer->isActive()){
        connectTimer->start();
    }
}

void QTcpSocketConnectionC::slot_openSocket()
{
    connectTimer = new QTimer();
    connect(connectTimer,&QTimer::timeout,this,&QTcpSocketConnectionC::slot_reConnectSocket);
    if(!isOpen){
        tcpSocket = new QTcpSocket(nullptr);
        connect(tcpSocket,&QTcpSocket::readyRead,this,&QTcpSocketConnectionC::slot_tcpSocketReadyRead,Qt::DirectConnection);
        connect(tcpSocket,&QTcpSocket::connected,this,&QTcpSocketConnectionC::slot_tcpSocketConnected,Qt::DirectConnection);
        connect(tcpSocket,&QTcpSocket::disconnected,this,&QTcpSocketConnectionC::slot_tcpSocketDisconnected,Qt::DirectConnection);
        isOpen = true;
    }
    connectTimer->setInterval(1000);
    slot_reStartConnectTimer();
}

void QTcpSocketConnectionC::slot_closeSocket()
{
    if(connectTimer->isActive()){
        connectTimer->stop();
    }
    delete  connectTimer;
    if(isOpen){
        disconnect(tcpSocket); //断开信号槽
        tcpSocket->close();
        delete tcpSocket;
        isOpen = false;
    }
}

void QTcpSocketConnectionC::slot_reConnectSocket()
{
//    if(!isConnected){
//        qDebug() << __FUNCTION__ << address << port;
        tcpSocket->abort();
        tcpSocket->connectToHost(address,port);
        tcpSocket->setReadBufferSize(TCP_SOCKET_FRAME_LEN);
        //tcpSocket->waitForConnected(3000);
//    }
}

void QTcpSocketConnectionC::slot_sendData(QByteArray byteArray)
{
    QByteArray sendByteArray;
    sendByteArray.resize(TCP_SOCKET_FRAME_LEN);
    int sendDataLen = TCP_SOCKET_FRAME_LEN - sizeof(SocketFrameHeader);
    SocketFrameHeader socketFrameHeader;
    socketFrameHeader.packId = getSendPackId();
    socketFrameHeader.packLen = byteArray.size();
    socketFrameHeader.frameSerial = 0;//帧序号

    while(byteArray.size() > 0){
        socketFrameHeader.dataLen = byteArray.size() > sendDataLen ? sendDataLen : byteArray.size();
        if(byteArray.size() <= sendDataLen){
            socketFrameHeader.frameMark = FRAME_MARK_END;
        }else{
            socketFrameHeader.frameMark = FRAME_MARK_CENTER;
        }
        memcpy(sendByteArray.data(),&socketFrameHeader,sizeof(SocketFrameHeader));
        memcpy(sendByteArray.data() + sizeof(SocketFrameHeader),byteArray.data(),byteArray.size() > sendDataLen ? sendDataLen : byteArray.size());
        tcpSocket->write(sendByteArray);
        byteArray.remove(0,byteArray.size() > sendDataLen ? sendDataLen : byteArray.size());
        socketFrameHeader.frameSerial++;
        QThread::msleep(1);
    }
}

quint16 QTcpSocketConnectionC::getSendPackId()
{
    quint16 nowId = sendPackId;
    sendPackId++;
    return nowId;
}

void QTcpSocketConnectionC::parsingFrameData(const QByteArray &byteArray)
{
    //qDebug() << __FUNCTION__;
    recvFrameTempData.append(byteArray);
    while(recvFrameTempData.size() >= TCP_SOCKET_FRAME_LEN){
        SocketFrameHeader socketFrameHeader;
        //        if(byteArray.size() < sizeof (socketFrameHeader)){
        //            qCritical() << __FUNCTION__ << "The frame data is less than the frame header length.";
        //            return;
        //        }
        memcpy(&socketFrameHeader,recvFrameTempData,sizeof (socketFrameHeader));

        if(socketFrameHeader.syncMark != TCP_SYNC_MARK){
            qCritical() << __FUNCTION__ << "Sync mark error in frame header.";
            return;
        }

        if(socketFrameHeader.packId != recvPackId){
            //qCritical() << __FUNCTION__ << "packId != recvPackId";
            recvPackData.clear();
            recvPackId = socketFrameHeader.packId;
        }

        if(socketFrameHeader.frameSerial != nextFrameSerial){
            qCritical() << __FUNCTION__ << "The frame number does not match.";
            return;
        }

        nextFrameSerial++;

        QByteArray frameData;
        frameData.resize(socketFrameHeader.dataLen);
        memcpy(frameData.data(),recvFrameTempData.data()+sizeof (socketFrameHeader),socketFrameHeader.dataLen);
        recvPackData.append(frameData);


        if(socketFrameHeader.frameMark == FRAME_MARK_END){
            if(socketFrameHeader.packLen != recvPackData.size()){
                qCritical() << __FUNCTION__ << "The packet length does not match.";
                return;
            }else{
                //start dispose pack data
                emit signal_recvData(connectionId,recvPackData);
            }
            nextFrameSerial = 0;
            recvPackData.clear();
        }
        recvFrameTempData.remove(0,TCP_SOCKET_FRAME_LEN);
    }
}

void QTcpSocketConnectionC::run()
{
    exec();
}
